前面我們花了幾篇介紹概念性、原則性的東西,接下來我將整系列文章拆成 Backend
、Frontend
還有 Infrastructure
三大面向來依序講解,所以今天就讓我們從 Backend
切入吧!
目前 Modern Web 的腳色劃分通常是把 Backend 定位成 API Server,Frontend 則是一些 Single Page Application(SPA),兩邊再透過 Ajax 的方式傳遞 Json 格式的訊息來互動。
在我們 Boilerplate 中的 Backend 除了當作 API Server 之外,也用於 React 元件的 Server Side Render(SSR),SSR 是因應 SPA 的興起而逐漸被重視的一項技術,之後在 Infrastructure 的部分我們會詳加介紹。
所以實作 API Server 需要怎麼樣的 Technique Stack 呢?在 Node 的生態系統中已經有很多出色的 Library 或 Framework,像是 Express、Koa、Hapi,但回頭想想 Boilerplate 的目的是要提供 General 的標準與解法,所以我還是比較傾向使用熱門的、大家熟知的模組,也就是 Express。
Express
是幾乎所有接觸 Node 網站開發的人都熟知的模組,可以很簡易且快速地架出 Web Server:
import express from 'express';
let app = express();
app.get('/path/to/anywhere', (req, res) => {
res.json({
hello: 'world',
});
});
app.listen(3000, (err) => {
console.log('app started');
});
當然這只是一段 Hello World 的範例,和實際的 Server 有很大一段落差,後面的兩篇我們再來談談怎麼樣組織出有彈性而且容易維護的 Express API Server。
Backend 中有另一個重要的元素是資料庫,傳統上 PHP、Python、Ruby 較常使用關聯式資料庫(Relational Database),例如大家聽到爛掉的 MySQL,還有 MariaDB、PostgreSQL 等 SQL-Bsaed 的資料庫;但 Node 的生態中是以 JS 物件為基礎,資料儲存格式通常是 Json,所以慣例上是使用 MongoDB 這一類的 No-SQL 資料庫。
在實務上,我們不會直接使用原生寫法去存取資料庫,通常要使用 Node 存取 MongoDB 的話,還會再搭配所謂的 ORM(Object Relational Mapping)或是 ODM(Object Document Mapping),ORM 是針對 SQL-Bsaed 資料庫,ODM 是針對 No-SQL 資料庫,兩者意義是相同的,只是稱呼有些微差異而已。
ORM/ODM 是一種把資料庫操作抽象化的程式技巧,例如我們定義好 User
這個資料庫 Schema:
import mongoose from 'mongoose';
let UserSchema = new mongoose.Schema({
name: String,
email: {
value: String,
isVerified: Boolean,
verifiedAt: Date,
},
password: String,
});
let User = mongoose.model('User', UserSchema);
接著就能以 Program-Based 的方式(而不是 Query-Based)來操作資料庫了:
User.findById(req.params.userId, (err, user) => {
// 這邊使用 programming 的方式來更新物件
user.name = req.body.newName;
// 修改完成後存回資料庫
user.save((err, user) => {
console.log(user);
});
});
多了這樣一層包裝,對效率多少會有影響,但是 ORM/ODM 帶來的效益對整個產品和整個團隊是遠勝過執行速度降低的成本,簡言之就是利大於弊:
方便
如同上面範例所示,可以輕鬆地使用 Program-Based 的方式對資料進行任意操作,最後再使用 save
一次性寫回資料庫。
可以進行版本控制
資料庫的結構一般是無法保存在 Source Code 裡的,但若使用了 ORM/ODM,自然就會把 Schema 寫入 Source Code 中,讓資料庫的結構也能被追蹤,減少環境設定的疏失。
安全
通常 ORM/ODM 會內建一些文字的 Escape 機制,所以使用 SQL-Bsaed 資料庫的團隊就可以不用花心思去防止 Injection 之類的鳥事,進而把更多的時間專注在產品功能的開發。
在我們的 Boilerplate 中使用的是 Mongoose,堪稱 Node 界家喻戶曉的 ODM 模組。其實上面的兩段範例程式就是 Mongoose 的實際使用方式,程式碼也是擷取自 Boilerplate,它還包括了許多實用功能,像是欄位的驗證、虛擬欄位、自訂 Static Methods、自訂 Instance Methods 等等,詳細功能建議先 Google 教學文章來看,等到熟悉了再去啃官方文件。